home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / apps / sprdshts / viscalc.lzh / VISCALC / INTERP.C < prev    next >
C/C++ Source or Header  |  1985-11-20  |  15KB  |  616 lines

  1. /*    SC    A Spreadsheet Calculator
  2.  *        Expression interpreter and assorted support routines.
  3.  *
  4.  *        original by James Gosling, September 1982
  5.  *        modified by Mark Weiser and Bruce Israel, 
  6.  *            University of Maryland
  7.  *
  8.  *              More mods Robert Bond, 12/86
  9.  *        Major mods to run on VMS and AMIGA, 1/17/87
  10.  */
  11.  
  12. #include "sc.h"
  13. #define DEFCOLDELIM ':'
  14.  
  15. char *malloc();
  16.  
  17. double dosum(minr, minc, maxr, maxc)
  18. int minr, minc, maxr, maxc;
  19. {
  20.     double v;
  21.     register r,c;
  22.     register struct ent *p;
  23.  
  24.     v = 0;
  25.     for (r = minr; r<=maxr; r++)
  26.     for (c = minc; c<=maxc; c++)
  27.         if ((p = tbl[r][c]) && p->flags&is_valid)
  28.         v += p->v;
  29.     return v;
  30. }
  31.  
  32. double doprod(minr, minc, maxr, maxc)
  33. int minr, minc, maxr, maxc;
  34. {
  35.     double v;
  36.     register r,c;
  37.     register struct ent *p;
  38.  
  39.     v = 1;
  40.     for (r = minr; r<=maxr; r++)
  41.     for (c = minc; c<=maxc; c++)
  42.         if ((p = tbl[r][c]) && p->flags&is_valid)
  43.         v *= p->v;
  44.     return v;
  45. }
  46.  
  47. double doavg(minr, minc, maxr, maxc)
  48. int minr, minc, maxr, maxc;
  49. {
  50.     double v;
  51.     register r,c,count;
  52.     register struct ent *p;
  53.  
  54.     v = 0;
  55.     count = 0;
  56.     for (r = minr; r<=maxr; r++)
  57.     for (c = minc; c<=maxc; c++)
  58.         if ((p = tbl[r][c]) && p->flags&is_valid) {
  59.         v += p->v;
  60.         count++;
  61.         }
  62.  
  63.     return (v / (double)count);
  64. }
  65.  
  66. double eval(e)
  67. register struct enode *e; {
  68.     if (e==0) return 0;
  69.     switch (e->op) {
  70.     case '+':    return (eval(e->e.o.left) + eval(e->e.o.right));
  71.     case '-':    return (eval(e->e.o.left) - eval(e->e.o.right));
  72.     case '*':    return (eval(e->e.o.left) * eval(e->e.o.right));
  73.     case '/':     {    double denom = eval (e->e.o.right);
  74.             return denom ? eval(e->e.o.left) / denom : 0; }
  75.     case '<':    return (eval(e->e.o.left) < eval(e->e.o.right));
  76.     case '=':    return (eval(e->e.o.left) == eval(e->e.o.right));
  77.     case '>':    return (eval(e->e.o.left) > eval(e->e.o.right));
  78.     case '&':    return (eval(e->e.o.left) != 0.0 &&
  79.                    eval(e->e.o.right) != 0.0) ? 1.0 : 0.0;
  80.     case '|':    return (eval(e->e.o.left) != 0.0 ||
  81.                    eval(e->e.o.right) != 0.0) ? 1.0 : 0.0;
  82.     case '?':    return eval(e->e.o.left) ? eval(e->e.o.right->e.o.left)
  83.                          : eval(e->e.o.right->e.o.right);
  84.     case 'm':    return (-eval(e->e.o.right));
  85.     case 'f':    return (eval(e->e.o.right));
  86.     case '~':    return (!eval(e->e.o.right));
  87.     case 'k':    return (e->e.k);
  88.     case 'v':    return (e->e.v->v);
  89.     case O_REDUCE('+'):
  90.      case O_REDUCE('*'):
  91.      case O_REDUCE('a'):
  92.         {
  93. #ifdef TOS
  94.             register r,c;
  95.         int maxr, maxc;
  96.         int minr, minc;
  97. #else
  98.             register r,c;
  99.         register maxr, maxc;
  100.         register minr, minc;
  101. #endif
  102.         maxr = ((struct ent *) e->e.o.right) -> row;
  103.         maxc = ((struct ent *) e->e.o.right) -> col;
  104.         minr = ((struct ent *) e->e.o.left) -> row;
  105.         minc = ((struct ent *) e->e.o.left) -> col;
  106.         if (minr>maxr) r = maxr, maxr = minr, minr = r;
  107.         if (minc>maxc) c = maxc, maxc = minc, minc = c;
  108.             switch (e->op) {
  109.                 case O_REDUCE('+'): return dosum(minr, minc, maxr, maxc);
  110.                  case O_REDUCE('*'): return doprod(minr, minc, maxr, maxc);
  111.                  case O_REDUCE('a'): return doavg(minr, minc, maxr, maxc);
  112.         }
  113.         }
  114.     }
  115. }
  116.  
  117. #define MAXPROP 7
  118.  
  119. EvalAll () {
  120.     int lastct,repct = 0;
  121.  
  122.     while ((lastct = RealEvalAll()) && (repct++ <= MAXPROP));
  123.  
  124.     repct--;
  125. }
  126.  
  127. int RealEvalAll () {
  128.     register i,j;
  129.     int chgct = 0;
  130.     register struct ent *p;
  131.     for (i=0; i<=maxrow; i++)
  132.     for (j=0; j<=maxcol; j++)
  133.         if ((p=tbl[i][j]) && p->expr) {
  134.         double v = eval (p->expr);
  135.         if (v != p->v) {
  136.             p->v = v; chgct++;
  137.             p->flags |= (is_changed|is_valid);
  138.         }
  139.         }
  140.     return(chgct);
  141. }
  142.  
  143. struct enode *new(op,a1,a2)
  144. struct enode *a1, *a2; {
  145.     register struct enode *p = (struct enode *) malloc (sizeof (struct enode));
  146.     p->op = op;
  147.     switch (op) {
  148.     case O_VAR: p->e.v = (struct ent *) a1; break;
  149.     case O_CONST: p->e.k = *(double *)&a1; break;
  150.     default: p->e.o.left = a1; p->e.o.right = a2;
  151.     }
  152.     return p;
  153. }
  154.  
  155. copy (dv, v1, v2)
  156. struct ent *dv, *v1, *v2;
  157. {
  158.     register r,c;
  159.     register struct ent *p;
  160.     register struct ent *n;
  161.     register deltar, deltac;
  162.     int maxr, maxc;
  163.     int minr, minc;
  164.     int dr, dc;
  165.  
  166.     dr = dv->row;
  167.     dc = dv->col;
  168.     maxr = v2->row;
  169.     maxc = v2->col;
  170.     minr = v1->row;
  171.     minc = v1->col;
  172.     if (minr>maxr) r = maxr, maxr = minr, minr = r;
  173.     if (minc>maxc) c = maxc, maxc = minc, minc = c;
  174.     if (dr+maxr-minr >= MAXROWS  || 
  175.            dc+maxc-minc >= MAXCOLS) {
  176.     error ("The table can't be any bigger");
  177.     return;
  178.     }
  179.     deltar = dr-minr;
  180.     deltac = dc-minc;
  181.     FullUpdate++;
  182.     for (r = minr; r<=maxr; r++)
  183.     for (c = minc; c<=maxc; c++) {
  184.         n = lookat (r+deltar, c+deltac);
  185.         clearent(n);
  186.         if (p = tbl[r][c]) {
  187.         n -> v = p -> v;
  188.         n -> flags = p -> flags;
  189.         n -> expr = copye(p->expr, deltar, deltac);
  190.         n -> label = 0;
  191.         if (p -> label) {
  192.             n -> label = (char *)
  193.                  malloc (strlen (p -> label) + 1);
  194.             strcpy (n -> label, p -> label);
  195.         }
  196.         }
  197.     }
  198. }
  199.  
  200. let (v, e)
  201. struct ent *v;
  202. struct enode *e; {
  203.     efree (v->expr);
  204.     if (constant(e)) {
  205.     v->v = eval(e);
  206.     v->expr = 0;
  207.     efree(e);
  208.     } else
  209.     v->expr = e;
  210.     v->flags |= (is_changed|is_valid);
  211.     changed++;
  212.     modflg++;
  213. }
  214.  
  215. clearent (v)
  216. struct ent *v; {
  217.     if (!v)
  218.     return;
  219.     label(v,"",-1);
  220.     v->v = 0;
  221.     if (v->expr)
  222.     efree(v->expr);
  223.     v->expr = 0;
  224.     v->flags |= (is_changed);
  225.     v->flags &= ~(is_valid);
  226.     changed++;
  227.     modflg++;
  228. }
  229.  
  230. constant(e)
  231. register struct enode *e; {
  232.     return e==0 || e->op == O_CONST 
  233.     || (e->op != O_VAR
  234.      && (e->op&~0177) != O_REDUCE(0)
  235.      && constant (e->e.o.left)
  236.      && constant(e->e.o.right));
  237. }
  238.  
  239. efree (e)
  240. register struct enode *e; {
  241.     if (e) {
  242.     if (e->op != O_VAR && e->op !=O_CONST && (e->op&~0177) != O_REDUCE(0)) {
  243.         efree (e->e.o.left);
  244.         efree (e->e.o.right);
  245.     }
  246.     free (e);
  247.     }
  248. }
  249.  
  250. label (v, s, flushdir)
  251. register struct ent *v;
  252. register char *s; {
  253.     if (v) {
  254.     if (flushdir==0 && v->flags&is_valid) {
  255.         register struct ent *tv;
  256.         if (v->col>0 && ((tv=lookat(v->row,v->col-1))->flags&is_valid)==0)
  257.         v = tv, flushdir = 1;
  258.         else if (((tv=lookat (v->row,v->col+1))->flags&is_valid)==0)
  259.         v = tv, flushdir = -1;
  260.         else flushdir = -1;
  261.     }
  262.     if (v->label) free(v->label);
  263.     if (s && s[0]) {
  264.         v->label = (char *) malloc (strlen(s)+1);
  265.         strcpy (v->label, s);
  266.     } else v->label = 0;
  267.     v->flags |= is_lchanged;
  268.     if (flushdir<0) v->flags |= is_leftflush;
  269.     else v->flags &= ~is_leftflush;
  270.     FullUpdate++;
  271.     modflg++;
  272.     }
  273. }
  274.  
  275. decodev (v)
  276. register struct ent *v; {
  277.     if (v) sprintf (line+linelim, "%s%d", coltoa(v->col), v->row);
  278.     else sprintf (line+linelim,"VAR?");
  279.     linelim += strlen (line+linelim);
  280. }
  281.  
  282. char *
  283. coltoa(col)
  284. int col;
  285. {
  286.     static char rname[3];
  287.     register char *p = rname;
  288.  
  289.     if (col < 0 || col > 25*26) 
  290.     debug("coltoa: invalid col: %d", col);
  291.  
  292.     if (col > 25) {
  293.     *p++ = col/26 + 'A' - 1;
  294.     col %= 26;
  295.     }
  296.     *p++ = col+'A';
  297.     *p = 0;
  298.     return(rname);
  299. }
  300.  
  301. decompile(e, priority)
  302. register struct enode *e; {
  303.     register char *s;
  304.     if (e) {
  305.     int mypriority;
  306.     switch (e->op) {
  307.     default: mypriority = 99; break;
  308.     case '?': mypriority = 1; break;
  309.     case ':': mypriority = 2; break;
  310.     case '|': mypriority = 3; break;
  311.     case '&': mypriority = 4; break;
  312.     case '<': case '=': case '>': mypriority = 6; break;
  313.     case '+': case '-': mypriority = 8; break;
  314.     case '*': case '/': mypriority = 10; break;
  315.     }
  316.     if (mypriority<priority) line[linelim++] = '(';
  317.     switch (e->op) {
  318.     case 'f':    { 
  319.                 for (s="fixed "; line[linelim++] = *s++;);
  320.                 linelim--;
  321.                 decompile (e->e.o.right, 30);
  322.                 break;
  323.             }
  324.     case 'm':    line[linelim++] = '-';
  325.             decompile (e->e.o